package com.conversationboard.tree;

import java.sql.SQLException;
import java.util.List;

import com.conversationboard.model.Board;
import com.conversationboard.model.Boards;
import com.conversationboard.model.User;
import com.conversationboard.model.propertybag.Property;
import com.conversationboard.model.propertybag.PropertyBag;
import com.conversationboard.serialisation.XmlSerialiser;

public class Folders {

	private static Folders instance = null;
	private Node root;


	private Folders() {
	}


	public int getNextNodeId() throws SQLException {

		int currentMaximumNodeId = this.getRoot().getMaxNodeId(0);
		return ++currentMaximumNodeId;

	}


	public static Folders getInstance() throws SQLException {

		if (instance == null) {

			Property property = PropertyBag.get("folders");

			/* If there is no board structure set up, then mimic the flat list and copy all
			 * boards into it to start with. */

			if ((property == null) || (property.getValue() == null)) {

				instance = new Folders();

				Node rootNode = new Node(null);
				rootNode.setNodeType(NodeType.Folder);
				rootNode.setFolderName("Root Folder");
				rootNode.setRoot(true);

				instance.setRoot(rootNode);

				for (Board board : Boards.getAllBoards()) {
					Node node = new Node(rootNode);
					node.setBoardId(board.getBoardId());

					rootNode.addChildNode(node);
				}

				instance.store();

			} else {
				instance = Folders.deserialise(property.getValue());
			}
		}

		return instance;
	}


	private static Folders deserialise(String xml) {

		XmlSerialiser<Folders> serialiser = new XmlSerialiser<Folders>();
		serialiser.setAlias("Folders", Folders.class);
		serialiser.setAlias("Node", Node.class);
		Folders folders = serialiser.deSerialise(xml);

		return folders;
	}


	public void store() throws SQLException {

		XmlSerialiser<Folders> serialiser = new XmlSerialiser<Folders>();
		serialiser.setAlias("Folders", Folders.class);
		serialiser.setAlias("Node", Node.class);
		String xml = serialiser.serialise(this);

		PropertyBag.put("folders", xml);
	}


	public Node getRoot() {
		return root;
	}


	public void setRoot(Node root) {
		this.root = root;
	}


	public String drawTree(User user, boolean addNodeIDs) throws SQLException {

		StringBuilder buffer = new StringBuilder();

		buffer.append("<span class=\"blue\">" + this.getRoot().getFolderName() + "</span>\n");
		this.getRoot().drawTree(user, 1, buffer, addNodeIDs);

		return buffer.toString();

	}


	public void moveFolder(User user, int sourceFolderId, int targetFolderId) throws SQLException {

		/* You can't move the root folder */

		if (sourceFolderId == 0) {
			return;
		}

		/* Get a handle to the source folder, remove it from its parent's node list and then add it
		 * to the new folder's child list, then store everything. */

		Node folder = Folders.getInstance().getRoot().findFolder(sourceFolderId);
		folder.getParentNode().removeChildFolder(user, sourceFolderId);
		Folders.getInstance().getRoot().findFolder(targetFolderId).addChildNode(folder);

		Folders.getInstance().store();

	}


	public void moveBoard(User user, int nodeId, Position position, int targetNodeId) throws SQLException {

		Node root = Folders.getInstance().getRoot();

		Node sourceNode = root.findNode(nodeId);
		Node targetNode = root.findNode(targetNodeId);
		Node targetNodeParent = targetNode.getParentNode();

		targetNodeParent.addChildNode(user, sourceNode, position, targetNode);

		/* The parent node might have changed, so update it with the target node's parent node */
		sourceNode.setParentNode(targetNode.getParentNode());
		Folders.getInstance().getRoot().removeChildNode(user, nodeId, true);

		Folders.getInstance().store();
	}


	public void removeNode(User user, int nodeId) throws SQLException {

		List<Node> nodes = this.getRoot().getChildNodes(user, true);
		Node nodeToRemove = null;

		for (Node node : nodes) {
			if (node.getNodeId() == nodeId) {
				nodeToRemove = node;
				break;
			}
		}

		if (nodeToRemove != null) {
			nodeToRemove.getParentNode().removeChildNode(nodeToRemove);
		}

	}

}
